﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;
using Volo.Abp.ObjectMapping;
using Volo.Abp.Users;
using WMSSystem.DYB.Dto.LocationManagement.Input;
using WMSSystem.DYB.Dto.LocationManagement.Output;
using WMSSystem.DYB.Dto.PositionManagement.Input;
using WMSSystem.DYB.Dto.PositionManagement.Output;
using WMSSystem.DYB.Interface;
using WMSSystem.YSL.Interfance;

namespace WMSSystem.DYB.Application
{
    public class PositionService : ApplicationService, IApplicationService, IPositionService
    {
        private readonly IRepository<IdentityUser, Guid> _userRepository;
        private readonly IRepository<PositionManagement, Guid> _positionRepository;
        private readonly IRepository<LocationManagement,Guid> _locationManagementRepository;
        private readonly ICodeRuleAppService _codeRuleAppService;
        public PositionService(IRepository<IdentityUser, Guid> userRepository, IRepository<PositionManagement, Guid> positionRepository, IRepository<LocationManagement, Guid> locationManagementRepository, ICodeRuleAppService codeRuleAppService)
        {
            _userRepository = userRepository;
            _positionRepository = positionRepository;
            _locationManagementRepository = locationManagementRepository;
            _codeRuleAppService = codeRuleAppService;
        }
        /// <summary>
        /// 新建仓位
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ApiResponse<CreatePositioinInput>> CreatePosition(CreatePositioinInput input)
        {
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    var model = ObjectMapper.Map<CreatePositioinInput, PositionManagement>(input);
                    model.Num = 0;
                    model.Code = await _codeRuleAppService.GenerateCodeAsync("position");
                    model.CreatorId = new Guid("3a1b4d19-6f9c-7e5e-9f1f-ce1da55e4f1e");
                    model.LastModificationTime = DateTime.Now;
                    model.LastModifierId = new Guid("3a1b4d19-6f9c-7e5e-9f1f-ce1da55e4f1e");
                    
                    var location = await _locationManagementRepository.GetAsync(x => x.Id == input.LocationManagementId);
                    var num = location.UseCapacity + model.Capacity;
                    if (num>location.Capacity)
                    {
                        throw new Exception("新建仓位失败，仓位容量超过库位容量限制");
                        //scope.Dispose();
                        //return new ApiResponse<CreatePositioinInput>()
                        //{
                        //    Code = ErrorCode.Error,
                        //    Message = "新建仓位失败，仓位容量超过库位容量限制",
                        //    Data = input
                        //};
                    }
                    location.Num += 1;
                    location.UseCapacity += model.Capacity;
                    await _positionRepository.InsertAsync(model);
                    await _locationManagementRepository.UpdateAsync(location);
                    scope.Complete();
                    return new ApiResponse<CreatePositioinInput>()
                    {
                        Code = ErrorCode.Success,
                        Message = "新建仓位成功",
                        Data = input
                    };
                }
                catch (Exception ex)
                {
                    return new ApiResponse<CreatePositioinInput>()
                    {
                        Code = ErrorCode.Error,
                        Message = ex.Message,
                        Data = input
                    };
                    throw;
                }
            }
        }
        /// <summary>
        /// 删除仓位
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<Guid> Delete(Guid Id)
        {
            var position = await _positionRepository.GetAsync(Id);
            var location = await _locationManagementRepository.GetAsync(position.LocationManagementId);
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    await _positionRepository.DeleteAsync(position);
                    location.Num -= 1;
                    location.UseCapacity -= position.Capacity;
                    await _locationManagementRepository.UpdateAsync(location);
                    scope.Complete();
                    return position.Id;
                }
                catch (Exception ex)
                {
                    throw;
                }
            }
        }
        /// <summary>
        /// 根据Id获取仓位详情
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<GetPosition> GetPosition(Guid Id)
        {
            var position = await _positionRepository.GetAsync(Id);
            var users = await _userRepository.GetAsync(position.PositionSupervisorId);
            Expression<Func<IdentityUser, bool>> expression = x => x.Id == position.CreatorId;
            var userss = await _userRepository.GetAsync(expression);
            GetPosition output = ObjectMapper.Map<PositionManagement, GetPosition>(position);
            output.PositionSupervisorName = users.UserName;
            output.CreatorName = userss.UserName;
            output.LastModifierName = "admin";
            return output;
        }
        /// <summary>
        /// 根据库位Id获取对应仓位数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<List<GetPositionList>> GetPositionList(GetPositionListInput input)
        {
            var positionlist = await _positionRepository.GetQueryableAsync();
            var userlist = await _userRepository.GetQueryableAsync();
            positionlist = positionlist.Where(x => x.LocationManagementId == input.LocationManagementId);
            var output = from a in positionlist
                         join c in userlist on a.PositionSupervisorId equals c.Id
                         select new GetPositionList
                         {
                             Capacity = a.Capacity,
                             Code = a.Code,
                             Id = a.Id,
                             State = a.State,
                             Name = a.Name,
                             Remark = a.Remark,
                             LastModifierName = "admin",
                             LastModificationTime = a.LastModificationTime,
                             StoreItems= a.StoreItems,
                             ExpirationDate = a.ExpirationDate,
                             Num = a.Num,
                             PositionSupervisorName = c.UserName
                         };
            return output.ToList();
        }
    }
}
